﻿using SQLite;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Games.Data
{
    class DataBase : IDataBase
    {
        private readonly SQLiteAsyncConnection _database;
        private static string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "data.db3");

        public DataBase()
        {
            _database = new SQLiteAsyncConnection(dbPath);
            _database.CreateTableAsync<GameArgs>();
        }
        public void DropTable<T>() where T : Entity, new()
        {
            _database.DropTableAsync<T>().Wait();
        }

        public void CreateTable<T>() where T : Entity, new()
        {
            _database.CreateTableAsync<T>().Wait();
        }

        public async Task<Paged<T>> GetPageAsync<T>(Expression<Func<T, bool>> expression, Sorter<T> sorter, int pageIndex, int pageSize) where T : Entity, new()
        {
            var query = _database.Table<T>();
            if(expression != null)
            {
                query = query.Where(expression);
            }
            query = (sorter ?? Sorter<T>.Default).Sort(query);
            var data = await query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
            return new Paged<T>
            {
                Data = data,
                PageIndex = pageIndex,
                PageSize = pageSize
            };
        }
        public Task<T> GetFirstOrDefaultAsync<T>(Expression<Func<T, bool>> expression, Sorter<T> sorter) where T : Entity, new()
        {
            var query = _database.Table<T>();
            if(expression != null)
            {
                query = query.Where(expression);
            }
            query = (sorter ?? Sorter<T>.Default).Sort(query);
            return query.FirstOrDefaultAsync();
        }

        public Task<T> GetAsync<T>(int id) where T : Entity, new()
        {
            return _database.Table<T>().FirstOrDefaultAsync(i => i.ID == id);
        }

        public Task<int> SaveAsync<T>(T t) where T : Entity, new()
        {
            if(t.ID != 0)
            {
                return _database.UpdateAsync(t);
            }
            else
            {
                return _database.InsertAsync(t);
            }
        }

        public Task<int> DeleteAsync<T>(int id) where T : Entity, new()
        {
            return _database.DeleteAsync<T>(id);
        }

        public Task<List<T>> GetAllAsync<T>(Expression<Func<T, bool>> expression, Sorter<T> sorter) where T : Entity, new()
        {
            var query = _database.Table<T>();
            if(expression != null)
            {
                query = query.Where(expression);
            }
            query = (sorter ?? Sorter<T>.Default).Sort(query);
            return query.ToListAsync();
        }
    }
}
